package model;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.lang.reflect.Constructor;
public final class ConstructorDeclared implements StatementKind, Comparable<ConstructorDeclared>{
	
	 private List<Class<?>> inputTypesCached;
	  private Class<?> outputTypeCached;

	  private final Constructor<?> constructor;
	  private ConstructorDeclared(Constructor<?> constructor) {
		    if (constructor == null)
		      throw new IllegalArgumentException("constructor should not be null.");
		    this.constructor = constructor;
		    this.constructor.setAccessible(true);
		  }

	  public static ConstructorDeclared getConstructor(Constructor<?> constructor) {
		    return new ConstructorDeclared(constructor);
	}
	  public Constructor<?> getConstructor(){
		  return this.constructor;
	  }
	  
	  public List<Class<?>> getInputTypes() {
		    if (inputTypesCached == null) {
		      inputTypesCached = new ArrayList<Class<?>>(Arrays.asList(constructor.getParameterTypes()));
		    }
		    return inputTypesCached;
		  }
	  public Class<?> getOutputType() {
		    if (outputTypeCached == null) {
		      outputTypeCached = constructor.getDeclaringClass();
		    }
		    return outputTypeCached;
		  }
	  public  String toParseableString(Map<String,Class<?>> classesToTest){
		  if(classesToTest.containsKey(this.constructor.getName()))
			  	return toString1(this.constructor);
		  return null;
	  }
	   
	  public String convertString(){
		  return this.toString1(this.constructor);
	  }
	  @Override
	  public String toString() {
	    return convertString();
	  }

	  public  String toString1(Constructor<?> c) {
		     StringBuilder sb = new StringBuilder();
		     sb.append(c.getName() + ".<init>(");
		     Class<?>[] params = c.getParameterTypes();
		     for (int j = 0; j < params.length; j++) {
		       sb.append(params[j].getName());
		       if (j < (params.length - 1))
		         sb.append(",");
		     }
		     sb.append(")");
		     
		     return sb.toString();
		   }
	  
		@Override
		public int compareTo(ConstructorDeclared o) {
			Constructor<?> thisConstructor=this.getConstructor();
			final int compareClazz = thisConstructor.getName().compareTo(o.getConstructor().getName());
			if(compareClazz != 0) return compareClazz;
			int thisConstructorParam=thisConstructor.getParameterTypes().length;
			int otherConstructorParams=o.getConstructor().getParameterTypes().length;
			if(thisConstructorParam != otherConstructorParams) return thisConstructorParam - otherConstructorParams;


			return 0;
		}
		
	
	  
}